package otSpaces.util;

import java.util.HashMap;
import java.util.Map;

import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;

public interface TreeModel {

	public static class Impl extends DefaultMutableTreeNode implements
			TreeModel {

		public static interface Selected {
			void selected(TreeModel node);
		}

		private static final long serialVersionUID = 1149665775169538776L;
		private final JTree _jTree;
		private final Map<String, Object> _mappings = new HashMap<String, Object>();
		private final Impl _parent;
		private final boolean _selectable;

		private final Selected _selected;

		private Impl(final Impl parent, final String name,
				final boolean selectable, final Selected selected) {
			super(name);

			_selected = selected;
			_selectable = selectable;
			_parent = parent;
			_jTree = _parent == null ? new JTree(this) : null;

		}

		public Impl(final String name, final Selected selected) {
			this(null, name, false, selected);

			_jTree.addTreeSelectionListener(new TreeSelectionListener() {

				@Override
				public void valueChanged(TreeSelectionEvent e) {
					final Impl last = (Impl) e.getPath().getLastPathComponent();

					if (last._selectable) {
						_selected.selected(last);
					}
				}
			});
		}

		@Override
		public TreeModel branch(final String name, boolean selectable) {
			final Impl ret = new Impl(this, name, selectable, _selected);

			add(ret);

			return ret;
		}

		@Override
		public JTree getJTree() {
			return _parent == null ? _jTree : _parent.getJTree();
		}

		@Override
		public Map<String, Object> getMappings() {
			return _mappings;
		}

		@Override
		public String getName() {
			return userObject.toString();
		}

		@Override
		public void prune() {
			if (_parent != null) {
				_parent.remove(this);
			}
		}

		@Override
		public void setName(String name) {
			userObject = name;
		}
	}

	TreeModel branch(final String name, boolean selectable);

	JTree getJTree();

	public Map<String, Object> getMappings();

	public String getName();

	void prune();

	public void setName(String name);

}